<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2021/4/9
 * Time: 18:28  ulimit -a  查看 socket 设置的总数 ，ulimit -n 10000 修改
 * 复用模型  基于非阻塞  ab -n 1000 -c 1000 -k http://123.0.0.1:9001/
 */
namespace Io\Multi;

class Worker
{
    // 接收
    public $onReceive = null;
    // 链接
    public $onConnect = null;

    public $onClose   = null;

    public $socket    = null;

    protected $sockets = [];

    public function __construct($socket_address)
    {
        $this->socket = stream_socket_server($socket_address);

        $this->sockets[(int)$this->socket] = $this->socket;

        stream_set_blocking($this->socket, 0);

        echo $socket_address.PHP_EOL;
    }

    public function index()
    {
        echo '111';
    }

    public function createSocket()
    {
        $client = @stream_socket_accept($this->socket);
        if (is_callable($this->onConnect)) {
            // 执行函数
            ($this->onConnect)($this, $client);
        }

        //return $client;
        $this->sockets[(int)$client] = $client;
    }

    public function sendMessage($client)
    {
        $data = fread($client, 65535);

        if ($data === '' || $data === false) {
            fclose($client);
            unset($this->sockets[(int)$client]);

            return null;
        }

        if (is_callable($this->onReceive)) {
            // 执行函数
            ($this->onReceive)($this, $client, $data);
        }
    }

    // 接收和链接处理事
    public function accept()
    {
        while (true) {

            $read = $this->socket;
            var_dump($this->sockets);
            stream_select($read, $w, $e, 1);
            var_dump($read);
            foreach ($read as $socket) {
                if ($socket == $this->socket) {
                    //  可能为主worker 也可能 stream_socket_accept 创建的链接

                    $this->createSocket();
                } else {
                    // 不是主worker 发送信息
                    $this->sendMessage($socket);
                }
            }
        }
    }

    public function start()
    {
        // 启动服务
        $this->accept();
    }

    public function send($conn, $data)
    {
        fwrite($conn, $data);
    }
}